home *** CD-ROM | disk | FTP | other *** search
- import os
- import sys
- import string
- from Tkinter import *
- from ScrolledText import ScrolledText
- from Dialog import Dialog
- import signal
-
- TK_READABLE = 1
- TK_WRITABLE = 2
- TK_EXCEPTION = 4
-
- BUFSIZE = 512
-
- class ShellWindow(ScrolledText):
-
- def __init__(self, master = None, cnf = {}):
- try:
- shell = cnf['shell']
- del cnf['shell']
- except KeyError:
- try:
- shell = os.environ['SHELL']
- except KeyError:
- shell = '/bin/sh'
- shell = shell + ' -i'
- args = string.split(shell)
- shell = args[0]
-
- ScrolledText.__init__(self, master, cnf)
- self.pos = '1.0'
- self.bind('<Return>', self.inputhandler)
- self.bind('<Control-c>', self.sigint)
- self.bind('<Control-t>', self.sigterm)
- self.bind('<Control-k>', self.sigkill)
- self.bind('<Control-d>', self.sendeof)
-
- self.pid, self.fromchild, self.tochild = spawn(shell, args)
- self.tk.createfilehandler(self.fromchild, TK_READABLE,
- self.outputhandler)
-
- def outputhandler(self, file, mask):
- data = os.read(file, BUFSIZE)
- if not data:
- self.tk.deletefilehandler(file)
- pid, sts = os.waitpid(self.pid, 0)
- print 'pid', pid, 'status', sts
- self.pid = None
- detail = sts>>8
- cause = sts & 0xff
- if cause == 0:
- msg = "exit status %d" % detail
- else:
- msg = "killed by signal %d" % (cause & 0x7f)
- if cause & 0x80:
- msg = msg + " -- core dumped"
- Dialog(self.master, {
- 'text': msg,
- 'title': "Exit status",
- 'bitmap': 'warning',
- 'default': 0,
- 'strings': ('OK',),
- })
- return
- self.insert('end', data)
- self.pos = self.index('end')
- self.yview_pickplace('end')
-
- def inputhandler(self, *args):
- if not self.pid:
- Dialog(self.master, {
- 'text': "No active process",
- 'title': "No process",
- 'bitmap': 'error',
- 'default': 0,
- 'strings': ('OK',),
- })
- return
- self.insert('end', '\n')
- line = self.get(self.pos, 'end')
- self.pos = self.index('end')
- os.write(self.tochild, line)
-
- def sendeof(self, *args):
- if not self.pid:
- Dialog(self.master, {
- 'text': "No active process",
- 'title': "No process",
- 'bitmap': 'error',
- 'default': 0,
- 'strings': ('OK',),
- })
- return
- os.close(self.tochild)
-
- def sendsig(self, sig):
- if not self.pid:
- Dialog(self.master, {
- 'text': "No active process",
- 'title': "No process",
- 'bitmap': 'error',
- 'default': 0,
- 'strings': ('OK',),
- })
- return
- os.kill(self.pid, sig)
-
- def sigint(self, *args):
- self.sendsig(signal.SIGINT)
-
- def sigquit(self, *args):
- self.sendsig(signal.SIGQUIT)
-
- def sigterm(self, *args):
- self.sendsig(signal.SIGTERM)
-
- def sigkill(self, *args):
- self.sendsig(signal.SIGKILL)
-
- MAXFD = 100 # Max number of file descriptors (os.getdtablesize()???)
-
- def spawn(prog, args):
- p2cread, p2cwrite = os.pipe()
- c2pread, c2pwrite = os.pipe()
- pid = os.fork()
- if pid == 0:
- # Child
- os.close(0)
- os.close(1)
- os.close(2)
- if os.dup(p2cread) <> 0:
- sys.stderr.write('popen2: bad read dup\n')
- if os.dup(c2pwrite) <> 1:
- sys.stderr.write('popen2: bad write dup\n')
- if os.dup(c2pwrite) <> 2:
- sys.stderr.write('popen2: bad write dup\n')
- for i in range(3, MAXFD):
- try:
- os.close(i)
- except:
- pass
- try:
- os.execvp(prog, args)
- finally:
- print 'execvp failed'
- os._exit(1)
- os.close(p2cread)
- os.close(c2pwrite)
- return pid, c2pread, p2cwrite
-
- def test():
- shell = string.join(sys.argv[1:])
- cnf = {}
- if shell:
- cnf['shell'] = shell
- root = Tk()
- root.minsize(1, 1)
- w = ShellWindow(root, cnf)
- w.pack({'expand': 1, 'fill': 'both'})
- w.focus_set()
- w.tk.mainloop()
-
- if __name__ == '__main__':
- test()
-